package com.raymond.http.netty;

import com.raymond.http.config.HttpConfig;
import io.netty.channel.Channel;
import io.netty.channel.pool.ChannelPoolHandler;
import io.netty.channel.pool.FixedChannelPool;
import io.netty.channel.pool.SimpleChannelPool;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestEncoder;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.SSLException;

/**
 * 默认通道池处理器
 *
 * @author :  raymond
 * @version :  V1.0
 * @date :  2021-12-11 17:32
 */
@Slf4j
public class DefaultChannelPoolHandler implements ChannelPoolHandler {

    private HttpConfig httpConfig;

    private HandlerInstance instance;

    private boolean isSsl;

    private HttpFixedChannelPool fixedChannelPool;

    public DefaultChannelPoolHandler(HttpConfig httpConfig, HandlerInstance instance, boolean isSsl) {
        this.httpConfig = httpConfig;
        this.instance = instance;
        this.isSsl = isSsl;
    }

    public void setFixedChannelPool(HttpFixedChannelPool fixedChannelPool) {
        this.fixedChannelPool = fixedChannelPool;
    }

    @Override
    public void channelReleased(Channel ch) {
//        log.debug("channelReleased. Channel ID:{}", ch.id());
    }

    @Override
    public void channelAcquired(Channel ch) {
//        log.debug("channelAcquired. Channel ID:{}", ch.id());
    }

    @Override
    public void channelCreated(Channel channel) throws SSLException {
        SocketChannel ch = (SocketChannel) channel;
        ch.config().setKeepAlive(httpConfig.getSoKeepAlive());
        ch.config().setTcpNoDelay(httpConfig.getTcpNodeLazy());
        //心跳连接，对长连接来说，如果连接时长时间未写入写出，则关闭连接
        //心跳模式配置，当一个通道多长时间未进行读写时断开
        channel.pipeline().addFirst(new ClientIdleStateTrigger());
        channel.pipeline().addFirst(new IdleStateHandler(httpConfig.getReaderIdleTimeSeconds(),
                httpConfig.getWriterIdleTimeSeconds(), httpConfig.getAllIdleTimeSeconds()));

        channel.pipeline().addLast(new HttpResponseDecoder());
        channel.pipeline().addLast(new HttpRequestEncoder());
        //最大传输字节控制
        channel.pipeline().addLast(new HttpObjectAggregator(httpConfig.getMaxContentLength()));
        if (isSsl) {
            SslContext context = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
            channel.pipeline().addLast(context.newHandler(channel.alloc()));
        }
        addHandler(channel);
    }

    protected void addHandler(Channel channel) {
        //in 绑定channel的handler
        channel.pipeline().addLast("httpClientHandler", instance.newInstance(fixedChannelPool));
    }
}
